/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bean.session;

import entity.CustomerAccountEntity;
import entity.DataObjectEntity;
import entity.ReservationEntity;
import entity.SalesOrderEntity;
import entity.SystemUserEntity;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.persistence.Query;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import type.SalesOrderStatus;

/**
 *
 * @author wei
 */
@Stateless
public class SalesOrderEntityFacade extends AbstractFacade<SalesOrderEntity> {

    @PersistenceContext(unitName = "MacTeam-warPU")
    private EntityManager em;
    
    @EJB
    private CustomerAccountEntityFacade customerAccountFacade;

    protected EntityManager getEntityManager() {
        return em;
    }

    public SalesOrderEntityFacade() {
        super(SalesOrderEntity.class);
    }
    @Resource
    SessionContext ctx;

    public void scheduleTimer(long milliseconds, long id) {
        ctx.getTimerService().createTimer(new Date(new Date().getTime() + milliseconds), id);
    }

    @Timeout
    public void timeoutHandler(Timer timer) {
        SalesOrderEntity s = em.find(SalesOrderEntity.class, timer.getInfo());
        s.setStatus(SalesOrderStatus.Rejected);
        em.merge(s);
        System.out.println(timer.getInfo());
        timer.cancel();
    }

    public void cancelTimer() {
        Collection<Timer> list = ctx.getTimerService().getTimers();
        Iterator<Timer> it = list.iterator();

        while (it.hasNext()) {
            Timer timer = it.next();
            timer.cancel();
        }
    }

    public DataModel searchSalesOrderById(String attribute, String input) {
        Query query = em.createQuery("SELECT s FROM SalesOrder s WHERE s." + attribute + " = " + input + " AND s.archived != 'true'");
        return new ListDataModel(query.getResultList());
    }

    public DataModel searchSalesOrderByName(String attribute, String input) {
        Query queryCustomer = em.createQuery("SELECT s FROM SalesOrder s INNER JOIN s.customer c WHERE CONCAT(c.first" + attribute + ", ' ', c.last" + attribute
                + ") LIKE '%" + input + "%' AND s.archived != 'true'");

        ArrayList query = new ArrayList<Object>();

        for (Object o : queryCustomer.getResultList()) {
            query.add(o);
        }
        return new ListDataModel(query);
    }

    public DataModel getAllSalesOrderForCustomer(long id) {
        Query query = em.createQuery("SELECT s FROM SalesOrder s INNER JOIN s.customer c WHERE c.id = " + id + " AND s.archived != 'true'");
        ArrayList salesOrder = new ArrayList<SalesOrderEntity>();

        for (Object o : query.getResultList()) {
            SalesOrderEntity s = (SalesOrderEntity) o;
            salesOrder.add(s);
        }
        return new ListDataModel(salesOrder);
    }

    public List<SalesOrderEntity> getPendingAndConfirmedSalesOrderForCustomer(long id) {
        Query query = em.createQuery("SELECT s FROM SalesOrder s INNER JOIN s.customer c WHERE c.id = " + id
                + " AND s.archived != 'true' AND (s.status=:typePending OR s.status=:typeConfirmed)");
        query.setParameter("typePending", SalesOrderStatus.Pending);
        query.setParameter("typeConfirmed", SalesOrderStatus.Confirmed);

        return query.getResultList();
    }

    public List<SalesOrderEntity> getSuspendedSalesOrderForCustomer(long id) {
        Query query = em.createQuery("SELECT s FROM SalesOrder s INNER JOIN s.customer c WHERE c.id = " + id
                + " AND s.archived != 'true' AND s.status=:suspended");
        query.setParameter("suspended", SalesOrderStatus.Suspended);

        return query.getResultList();
    }

    public SystemUserEntity getManagerFromDept(String department) {
        Query query = em.createQuery("SELECT DISTINCT d.manager FROM Department d WHERE d.name = '" + department + "'");
        SystemUserEntity manager = (SystemUserEntity) query.getSingleResult();
        System.out.println(manager.getName());
        return manager;
    }

    public List currentlyReserved(Long salesOrderID, String productName) {
        CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
        javax.persistence.criteria.CriteriaQuery cq = builder.createQuery();
        Root<DataObjectEntity> reservationRoot = cq.from(ReservationEntity.class);

        Predicate predicate1 = builder.equal(reservationRoot.get("salesOrder").get("id"), salesOrderID);
        Predicate predicate2 = builder.equal(reservationRoot.get("product").get("productName"), productName);

        cq.select(reservationRoot);
        cq.where(builder.and(predicate1, predicate2));
        return new ArrayList<ReservationEntity>(getEntityManager().createQuery(cq).getResultList());
    }

    public DataModel getAllSalesOrder() {
        Query query = em.createQuery("SELECT s FROM SalesOrder s WHERE s.archived!= 'true'");
        return new ListDataModel(query.getResultList());
    }

    public void markSalesOrderAsCompleted(SalesOrderEntity salesOrder) {
        salesOrder.setStatus(SalesOrderStatus.Completed);

        //check for CIA and decrease cash balance
        if (salesOrder.getCashPayable() > 0) {
            CustomerAccountEntity customerAccount = salesOrder.getCustomer().getCustomerAccount();
            double cashBalance = customerAccount.getCashBalance();
            double toDeduct = salesOrder.getCashPayable();

            cashBalance = cashBalance - toDeduct;
            customerAccount.setCashBalance(cashBalance);
            
            customerAccountFacade.edit(customerAccount);
        }

        edit(salesOrder);
    }
}
